#include <stdlib.h>
#include <string.h>

#include <debug.h>
#include <os_api.h>
#include <hal/gpio.h>
#include <hal/i2c.h>

#define TASK_STACK_SIZE (10 * 1024)
static char _task_stack[TASK_STACK_SIZE];

/******************************* STK8BA53: 3-axis Accelerometer *******************************/
#define STK8BA53_I2C_ADDRESS 0x18  // STK8BA53 I2C地址
void writeRegister(UINT8 regAddr, UINT8 value)
{
    hal_I2cWrite(I2C_CP_I2C, STK8BA53_I2C_ADDRESS, regAddr, &value, 1);
}

int readRegister(UINT8 regAddr, UINT8 *data)
{
    int st;

    st = hal_I2cRead(I2C_CP_I2C, STK8BA53_I2C_ADDRESS, regAddr, data, 1);
    return st;
}

void stk8ba53_read_acceleration(INT16 *x, INT16 *y, INT16 *z)
{
    UINT8 data[6];

    // 从寄存器0x02开始读取6个字节的数据
    hal_I2cRead(I2C_CP_I2C, STK8BA53_I2C_ADDRESS, 0x02, data, sizeof(data));

    // 组合成16位有符号整数
    *x = (data[0] << 8) | data[1];
    *y = (data[2] << 8) | data[3];
    *z = (data[4] << 8) | data[5];
}

void stk8ba53_init()
{
    hal_I2cInit(I2C_CP_I2C, FAST_MODE);
    writeRegister(0x20, 0x01); // 设置INTCFG1寄存器，例如选择推挽输出、高电平有效
    writeRegister(0x21, 0x00); // 设置INTCFG2寄存器，例如非锁存模式
    writeRegister(0x17, 0x10); // 启用新数据中断
}
/******************************* STK8BA53: 3-axis Accelerometer *******************************/

static void app_task(void *param)
{
    LOG_PRINTF("%s()... start...", __FUNCTION__);

    sleep(3); // wait system ready.

    stk8ba53_init();

    while (1)
    {
        int status;
        UINT8 intStatus;
        status = readRegister(0x0A, &intStatus); // 读取INTSTS2寄存器
        if (status == I2C_RC_OK && (intStatus & 0x80)) // 检查DATA_STS位是否置位
        {
            INT16 x, y, z;
            stk8ba53_read_acceleration(&x, &y, &z);
            LOG_PRINTF("Axis data X: %d, Y: %d, Z: %d", __FUNCTION__, x, y, z);
        }
        sleep(1); // 1 seconds
    }
}

int main()
{
    int ret;
    OSTaskRef task_ref; // because following task will never exit, so we do not use task handle, so we don't care it's handle

    ret = OSATaskCreate(&task_ref, _task_stack, TASK_STACK_SIZE, OS_APP_PRIORITY, "app", app_task, NULL);
    ASSERT(ret == OS_SUCCESS);
}
